<?php

namespace pc\models;
use common\helpers\Html;
use common\Service\JiebaService;
use common\Service\RedisService;
use Yii;


class Search
{
    public $queryString = '';
    public $queryWords = [];
    public $currentPage = 1;
    public $pageSize = 10;
    public $type = 0;  // 0:默认ALL 1：美女 2：写真 3：新闻
    private $redis;
    private $expire = 30 * 60 * 60;  //搜索结果过期时间设定 默认半个小时

    public $starFields = ['id','name','nick_name','desc','header'];
    public $newsFields = [];
    public $portrayFields = ['id','title','desc','star_id','create_time','relation_star','tags'];

    const TYPE_ALL = 0;
    const TYPE_STAR = 1;
    const TYPE_PORTRAY = 2;
    const TYPE_NEWS = 3;

    public function __construct()
    {
        $this->redis = Yii::$app->get('redis');
    }

    /*
     * 载入查询参数
     */
    public function load($params = []){
        isset($params['keyword']) && !empty($params['keyword']) && $this->queryString = trim($params['keyword']);
        $this->queryString = Html::safeFilterString($this->queryString);

        isset($params['page']) && $this->currentPage = intval($params['page']) ?: 1;
        isset($params['type']) && in_array(intval($params['type']),[1,2,3]) && $this->type = intval($params['type']);

        !empty($this->queryString) && $this->loadWords();
    }

    public function all(){
        $redisKey = 'searchWords:all:'.md5(json_encode($this->queryString));
        $exists = $this->redis->exists($redisKey);
        if(intval($exists) == 0){
            $starsIds = $this->stars();
            $portrayIds = $this->portrays();
            $newsIds = $this->news();

            if(!empty($portrayIds)){
                $portrayIds = array_map(function($value){
                    return $value . ':' . self::TYPE_PORTRAY;
                },$portrayIds);
            }
            if(!empty($starsIds)){
                $starsIds = array_map(function($value){
                    return $value . ':' . self::TYPE_STAR;
                },$starsIds);
            }
            if(!empty($newsIds)){
                $newsIds = array_map(function($value){
                    return $value . ':' . self::TYPE_NEWS;
                },$newsIds);
            }

            $allData = array_merge($portrayIds,$starsIds,$newsIds);
            //这里使用乾坤大挪移大法排序
            shuffle($allData);
            foreach ($allData as $value){
                $this->redis->lpush($redisKey,$value);
            }
            $this->redis->expire($redisKey,$this->expire);
        }

        $rs = RedisService::pageData($redisKey,$this->currentPage,$this->pageSize);

        if(!empty($rs['data'])){
            $tmpData = [];
            foreach ($rs['data'] as $value){
                $idType = explode(':',$value);
                $tmp = [];

                if($idType[1] == self::TYPE_STAR){
                    $tmp = Star::getStarInfoById($idType[0],$this->starFields);
                    !empty($tmp) && $tmp['searchType'] = self::TYPE_STAR;
                }

                if($idType[1] == self::TYPE_PORTRAY){
                    $tmp = Portray::getPortrayById($idType[0],$this->portrayFields);
                    !empty($tmp) && $tmp['searchType'] = self::TYPE_PORTRAY;
                }

                if($idType[1] == self::TYPE_NEWS){
                    $tmp = News::getNewsInfoById($idType[0],$this->newsFields);
                    !empty($tmp) && $tmp['searchType'] = self::TYPE_NEWS;
                }

                !empty($tmp) && $tmpData[] = $tmp;
            }
            $rs['data'] = $tmpData;
        }

        return $rs;
    }


    public function news(){
        $redisKey = 'searchWords:news:'.md5(json_encode($this->queryWords));
        $newsIds = [];

        $exists = $this->redis->exists($redisKey);
        if(intval($exists) == 0){
            $sql = "SELECT id FROM {{%news}} WHERE 1 = 2";
            foreach ($this->queryWords as $word){
                $sql .= " or title like '%{$word['name']}%' ";
            }
            $sql .= " order by id desc limit 100";

            $newsIds = Yii::$app->db->createCommand($sql)->queryAll();
            if(!empty($newsIds)){
                $newsIds = array_column($newsIds,'id');
                foreach ($newsIds as $newId){
                    $this->redis->rpush($redisKey,$newId);
                }
                $this->redis->expire($redisKey,$this->expire);
            }
        }

        if($this->type == self::TYPE_NEWS){
            $newsIds = RedisService::pageData($redisKey,$this->currentPage,$this->pageSize);
            !empty($newsIds['data']) && $newsIds['data'] = News::formatNews($newsIds['data'],$this->newsFields);
        }else{
            $newsIds = RedisService::pageData($redisKey,1,100)['data'];
        }

        return $newsIds;
    }



    public function portrays(){
        $redisKey = 'searchWords:portray:'.md5(json_encode($this->queryWords));
        $portraysIds = [];

        $exists = $this->redis->exists($redisKey);
        if(intval($exists) == 0){
            $portraysIds =  $this->unionIdsByTags('tagPortrayZset:');
            if(!empty($portraysIds['data'])){
                $portraysIds = $portraysIds['data'];
                foreach ($portraysIds as $portrayId){
                    $this->redis->rpush($redisKey,$portrayId);
                }
                $this->redis->expire($redisKey,$this->expire);
            }
        }

        if($this->type == self::TYPE_PORTRAY){
            $portraysIds = RedisService::pageData($redisKey,$this->currentPage,$this->pageSize);
            !empty($portraysIds['data']) && $portraysIds['data'] = Portray::formatPortrays($portraysIds['data'],$this->portrayFields);
        }else{
            $portraysIds = RedisService::pageData($redisKey,1,100)['data'];
        }

        return $portraysIds;
    }

    public function stars(){
        $redisKey = 'searchWords:star:'.md5(json_encode($this->queryString));
        $starIds = [];

        $exists = $this->redis->exists($redisKey);
        if(intval($exists) == 0){
            //优先明星名字检索
            $starIdsByName = $this->searchStarsByName();
            //关联标签检索明星
            $starIds =  $this->unionIdsByTags('tagZset:');
            //合并搜索的明星ID
            if(!empty($starIdsByName)){
                $starIds['data'] = isset($starIds['data']) ?  array_merge($starIdsByName,$starIds['data']) : $starIdsByName;
            }

            if(!empty($starIds['data'])){
                $starIds = $starIds['data'];

                foreach ($starIds as $starId){
                    $this->redis->rpush($redisKey,$starId);
                }
                $this->redis->expire($redisKey,$this->expire);
            }
        }

        if($this->type == self::TYPE_STAR){
            $starIds = RedisService::pageData($redisKey,$this->currentPage,$this->pageSize);
            !empty($starIds['data']) && $starIds['data'] = Star::formatStars($starIds['data'],$this->starFields);
        }else{
            $starIds = RedisService::pageData($redisKey,1,100)['data'];
        }

        return $starIds;
    }

    private function searchStarsByName(){
        $redisKey = 'searchWords:starByName:'.md5(json_encode($this->queryString));
        $exists = $this->redis->exists($redisKey);

        $result = [];
        if(intval($exists) == 0){
            $sql = "SELECT id FROM {{%star}} WHERE 1 = 2";

            //名字直接检索
            $sql .= " or name like '%{$this->queryString}%' ";
            $sql .= " or nick_name like '%{$this->queryString}%' ";

            foreach ($this->queryWords as $word){
                $sql .= " or name like '%{$word['name']}%' ";
                $sql .= " or nick_name like '%{$word['name']}%' ";
            }
            $sql .= " order by id desc limit 20";

            $starIds = Yii::$app->db->createCommand($sql)->queryAll();
            !empty($starIds) && $result = array_column($starIds,'id');

            if(!empty($result)){
                $this->redis->set($redisKey,json_encode($result));
                $this->redis->expire($redisKey,$this->expire);
            }
        }else{
            $result = $this->redis->get($redisKey);
            $result = json_decode($result,true);
        }

        return $result;
    }


    private function unionIdsByTags($redisKeyPre){
        if(empty($this->queryWords)) return [];

        $alias = array_column($this->queryWords,'alias');
        foreach ($alias as $key => $value){
            $alias[$key] = $redisKeyPre.$value;
        }

        $redisKey = RedisService::zUnionStore($alias);
        $rs = RedisService::pageData($redisKey,1,100,'zset');
        return $rs;
    }


    /*
     * 分词 有缓存 则读取缓存
     */
    private function loadWords(){
        $redisKey = 'searchWords:'.md5($this->queryString);
        $this->queryWords = $this->redis->get($redisKey);
        if($this->queryWords == NULL){
            echo 1;
            $jieBa = new JiebaService();
            $this->queryWords = $jieBa->getWords($this->queryString);
            unset($jieBa);
            if(!empty($this->queryWords)){
                $this->queryWords = Tags::parseTagsByName($this->queryWords);
            }
            $this->redis->set($redisKey,json_encode($this->queryWords));
            $this->redis->expire($redisKey,$this->expire);
        }else{
            $this->queryWords = json_decode($this->queryWords,true);
        }
    }







}
